﻿// ===============================================================================
// Project Name        :    Gfw.BLL.Basic.User
// Project Description :    
// ===============================================================================
// Class Name          :    UserGenealogyLogic
// Namespace:          :    Gfw.BLL.Basic.User
// Class Version       :    v1.0.0.0
// Class Description   :    
// CLR Version:        :    4.0.30319.17626
//Author               :    lif
// Machine             :    ADICO-PC
// Create Time         :    2012/7/1 9:46:47
// Update Time         :    2012/7/1 9:46:47
// ===============================================================================
// Copyright © lif 2012 . All rights reserved.
// ===============================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Gfw.BLL.Basic.Account;
using Gfw.Models.Admin;
using Gfw.Repositories.Admin;
using Gfw.Repository;
using Gfw.Web.Models.Genealogy;
using Gfw.Web.Models.User;

namespace Gfw.BLL.Basic.User
{
    public class UserGenealogyLogic
    {
        /// <summary>
        /// 二叉树结构算法
        /// </summary>
        /// <param name="loginName"></param>
        /// <param name="Code"></param>
        /// <returns>返回孩子最大条数</returns>
        public static int GetChildrenCount(string loginName, out string Code)
        {

            UsrUserRepository repository = new UsrUserRepository();
            var parent = repository.GetUserByLoginName(loginName);
            Code = parent.Code;
            var child = repository.GetMaxCodeUser(parent.Code);



            //模拟查询的条件，二叉树数值
            Int64 queryNumber = parent.CodeNumber;
            string queryCode = parent.Code;

            //通过数据库筛选，获取节点数最大的孩子节点
            //如果二叉树数值如下
            Int64 childNumber = child.CodeNumber;
            string childCode = child.Code;

            //计算节点的二进制值

            //计算查询节点和孩子节点在完整二叉树的度；based 1
            int queryH = (int) Math.Log(queryNumber, 2) + 1;
            int childH = (int) Math.Log(childNumber, 2) + 1;

            //计算字节点相对于查询节点的度
            int h = childH - queryH + 1;

            //计算孩子节点相对于查询节点的序号：based 1
            string relativeCode = "1" + childCode.Remove(0, queryCode.Length);
            //relativeNumber是相对于查询节点的序号，也是查询结果显示的总条数
             int relativeNumber;
            try
            {
                 relativeNumber = Convert.ToInt32(relativeCode, 2);
            }
            catch (Exception exp)
            {
                relativeNumber = int.MaxValue / 2;
            }

            return relativeNumber;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="rootCode"></param>
        /// <param name="pageIndex">页数，based：0</param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public static IList<UserGenealogyModel> GetGenealogy(string rootCode, int pageIndex, int pageSize)
        {
            if (rootCode == null)
                throw new NullReferenceException("未设置参数!");

            Int64 start = pageIndex*pageSize;
            Int64 end = (pageIndex + 1)*pageSize;
            string startCode = start == 0 ? rootCode : rootCode + Convert.ToString(start, 2).Remove(0, 1);
            string endCode = end == 0 ? rootCode : rootCode + Convert.ToString(end, 2).Remove(0, 1);
            Int64 startNumber = Convert.ToInt64(startCode, 2);
            Int64 endNumber = Convert.ToInt64(endCode, 2);

            UsrUserRepository repository = new UsrUserRepository();
            var users = repository.QueryChildrenRang(rootCode, startNumber, endNumber);

            //首先，将对象转换成为Model实体，并获取孩子节点个数
            var models = new List<UserGenealogyModel>();
            foreach (var user in users)
            {
                var model = user.CopyTo<UserGenealogyModel>();
                int left, right;
                repository.QueryChildrenCount(user.Code, out left, out right);
                model.LeftChildren = left;
                model.RightChildren = right;
                model.RecommenderName = user.RecommenderName;
                model.ParentName = user.ParentName;
                models.Add(model);
            }

            //查询的出来的条数不一定是完整的，现在需要进行二叉树补全
            //同时需要计算相对的度数和每层上面的需要

            for (int i = (int)start; i <(int) end; i++)
            {
                string code;
                var number = GetChildNumber(rootCode, i, out code);
                var select = models.Where(c => c.CodeNumber == number).FirstOrDefault();
                if (select == null)
                {
                    var model = new UserGenealogyModel()
                                    {
                                        Id = "",
                                        H = (int) Math.Log(i, 2) + 1,
                                        CodeNumber = number,
                                        Code = code,
                                        ParentHindex = GetParentHindex(i)
                                    };
                    model.Hindex = Math.Abs(i - (int) Math.Pow(2, model.H-1) +1);
                    models.Add(model);
                }
                else
                {

                    select.H = (int)Math.Log(i, 2) + 1;
                    select.Hindex = Math.Abs(i - (int)Math.Pow(2, select.H - 1) + 1);
                    select.ParentHindex = GetParentHindex(i);
                }

            }

            var query = from m in models orderby m.CodeNumber select m ;
           return query.ToList();
        }

        public static Int64 GetNextNeighbor(string rootCode, string currentCode)
        {
            string relativeCode = "1" + currentCode.Remove(0, rootCode.Length);
            Int64 relativeNumber = Convert.ToInt64(relativeCode, 2);
            Int64 relativeNextNumber = relativeNumber + 1;
            string relativeNextCode = Convert.ToString(relativeNextNumber, 2);
            string nextCode = rootCode + relativeNextCode.Remove(0, 1);
            Int64 nextNumber = Convert.ToInt64(nextCode, 2);

            return nextNumber;
        }

        /// <summary>
        /// 根据跟节点和相对关系，检查节点是否存在
        /// </summary>
        /// <param name="rootCode"></param>
        /// <param name="relativeNumber">相对关系数</param>
        /// <returns></returns>
        public static Int64 GetChildNumber(string rootCode, int relativeNumber, out string childCode)
        {
            childCode = "";
            if (relativeNumber <= 1)
                return Convert.ToInt64(rootCode, 2);
            string relativeCode = Convert.ToString(relativeNumber, 2);
            string code = rootCode + relativeCode.Remove(0, 1);
            childCode = code;
            Int64 number = Convert.ToInt64(code, 2);

            return number;
        }

        public static string GetChildCode(string rootCode, int relativeNumber)
        {
            if (relativeNumber == 0)
                return rootCode;
            string relativeCode = Convert.ToString(relativeNumber, 2);
            string code = rootCode + relativeCode.Remove(0, 1);
            return code;
        }


        public static string GetParentHindex(int relativeNumber)
        {
            if (relativeNumber == 1)
                return "-";
            int parentNumber = relativeNumber/2;
            int h = (int) Math.Log(parentNumber, 2) + 1;
            //int index = parentNumber - (int) Math.Log(parentNumber, 2);
            int index = (int)(parentNumber - Math.Pow(2, h - 1) + 1);
            return string.Format("{0}.{1}", h, index);
        }
    }
}
